# srcrepos/tools/srcrepos.py

import os
import zipfile
import tempfile

def generate(env):
  
    installed_files = dict()

    ##########################################################################
    # WriteValue
    ##########################################################################    
    
    def write_value_builder(target, source, env):
        f = open(target[0].get_abspath(), 'w')
        f.write(source[0].read())
        f.close()
        return None

    def write_value_generator(source, target, env, for_signature):
        return env.Action(write_value_builder, env.subst('write: $TARGET', target=target, source=source))

    env.Append(BUILDERS={'WriteValue': env.Builder(generator=write_value_generator)})

    ##########################################################################
    # Import Flags
    ##########################################################################    
    
    def import_flags(env, module):
        flags = env['SRCREPOS_FLAGS']
        if flags.has_key(module): 
            env.Append(**flags[module])
        return None
    
    env.AddMethod(import_flags, 'ImportFlags')

    ##########################################################################
    # Install and InstallAs
    ##########################################################################

    env.Tool('install')
    
    def track_installed_files(env, files):
        module = env['MODULE']
        try: installed_files[module]
        except: installed_files[module] = list()
        for f in files:
            install_dir = env.Dir('$PREFIX').get_abspath()
            if os.path.commonprefix([install_dir, f.get_abspath()]) == install_dir: 
                installed_files[module].append(f)
        return files

    def install(env, target, source, *args, **argv):
        return track_installed_files(env, env._InternalInstall(target, source, *args, **argv))

    def install_as(env, target, source, *args, **argv):
        return track_installed_files(env, env._InternalInstallAs(target, source, *args, **argv))

    env.AddMethod(install, 'Install')
    env.AddMethod(install_as, 'InstallAs')
    
    ##########################################################################
    # Package
    ##########################################################################   
    
    def upload_package_builder(target, source, env):
        prefix = env.Dir('$PREFIX').get_abspath()
        moduledesc = source[0].get_abspath()
        
        with tempfile.TemporaryFile() as tf:
            
            data_zip = zipfile.ZipFile(tf, 'w', compression=zipfile.ZIP_DEFLATED)
            map(lambda i: data_zip.write(i.get_abspath(), arcname=os.path.relpath(i.get_abspath(), prefix)),  source[1:])
            data_zip.close()
            tf.seek(0)
            
            desc = open(moduledesc, 'rU')
            package = zipfile.ZipFile(target[0].get_abspath(), 'w', compression=zipfile.ZIP_STORED)
            package.writestr('moduledesc.py', desc.read())
            package.writestr('data.zip', tf.read())
            package.close()
            desc.close()
            
            tf.close()
        
        return None

    def upload_package_generator(source, target, env, for_signature):
        return env.Action(upload_package_builder, env.subst('package: $TARGET', target=target, source=source))

    def create_upload_package(env):
        pkg_dir = env.Dir('#/../install/upload')
        packages = list()
        manifest = ['<?xml version="1.0"?>']
        manifest.append('<manifest>')
        for m in installed_files.keys():
            moduledesc = env.File('#/%s/moduledesc.py' % m)
            packages.extend(env.UploadPackage(env.File('package.zip', env.Dir(m, pkg_dir)), [ moduledesc ] + installed_files[m]))
            manifest.append('<entry module="%s" package="%s/package.zip" />' % (m, m))
        manifest.append('</manifest>\n')    
        upload_package = env.WriteValue(env.File('manifest.xml', pkg_dir), env.Value('<manifest>', built_value='\n'.join(manifest)))
        env.Depends(upload_package, packages)
        return upload_package
    
    env.Append(BUILDERS={'UploadPackage': env.Builder(generator=upload_package_generator)})
    env.AddMethod(create_upload_package, 'CreateUploadPackage')

    return None

def exists(env):
    # Is always available.
    return True


